/*
	Anonymous Image Board Image Downloader - program for downloading pictures from AIB
	Copyright (C) 2011-2012 Metallhead <Metallhead@megabox.ru>

	HomePage:    http://code.google.com/p/aibid/

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "downloads.h"

downloads::downloads(QString newUrl, QString newPath, int newIndex, bool hash, int limit, int updateTime, QDateTime addTime, bool loading, imageTypes alowedTypes):
	additionTime(addTime)
{
	upTime = updateTime;
	threadsLimit = limit;
	index = newIndex;
	seconds = 0;
	load = loading;
	timerActive = false;
	types = alowedTypes;

	download = new downloading(newUrl, newPath, hash, limit, alowedTypes);

	connect(download,SIGNAL(changeTimerState(int,bool)),this,SLOT(changeTimerState(int,bool)));
	connect(download,SIGNAL(statusChanged()),this,SLOT(statusChanged()));
	connect(download,SIGNAL(imagesCountChanged()),this,SLOT(imagesCountChanged()));
	connect(download,SIGNAL(folderInfoUpdate()),this,SLOT(folderInfoUpdate()));
	connect(&timer,SIGNAL(timeout()),this,SLOT(timerTick()));
	timeRemains.setInterval(1000);
	connect(&timeRemains,SIGNAL(timeout()),this,SLOT(timeRemainsUpdate()));
}
//download thread
void downloads::downloadThread()
{
	download->dbCheck();
	saveToRegistry(load);
	timer.setInterval(upTime*60000);
	setStatus(tr("Downloading html-code..."));
	QNetworkAccessManager * manager = new QNetworkAccessManager(this);
	connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(htmlCodeDownloaded(QNetworkReply*)));
	manager->get(QNetworkRequest(QUrl(download->url)));
}
//html-code downloaded
void downloads::htmlCodeDownloaded(QNetworkReply *reply)
{
	qDebug() << "html code downloaded";
	download->reply = reply;
	qDebug() << "starting parsing the html code";
	download->prepare();
}
//stop download
void downloads::stopThread()
{
	setStop(true);
	stopReplies();
}
//resume download
void downloads::resumeThread()
{
	setStatus(tr("Downloading html-code..."));
	QNetworkAccessManager *manager = new QNetworkAccessManager(this);
	connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(threadUpdate(QNetworkReply*)));
	manager->get(QNetworkRequest(QUrl(getUrl())));
}
//html-code downloaded while updated
void downloads::threadUpdate(QNetworkReply * reply)
{
	QDir dir(getPath());
	if(!dir.exists())
	{
		qDebug() << "making dir" << getPath();
		dir.mkpath(getPath());
		clearInfo();
	}
	qDebug() << "processing thread update";
	updateThread(reply);
}
//update thread
void downloads::updateThread(QNetworkReply * reply)
{
	setReply(reply);
	setStop(false);
	nullCounters();
	download->prepare();
}

void downloads::timerTick()
{
	qDebug() << "timer tick in thread #" << index << "with url" << getUrl();
	setStatus(tr("Downloading html-code..."));
	QNetworkAccessManager *manager = new QNetworkAccessManager(this);
	connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(threadUpdate(QNetworkReply*)));
	manager->get(QNetworkRequest(QUrl(getUrl())));
}

void downloads::changeTimerState(int num, bool newState)
{
	switch(num)
	{
	case 0:
		timer.stop();
		if(newState)
			timer.start();
		break;
	case 1:
		timeRemains.stop();
		seconds = 0;
		if(newState)
			timeRemains.start();
		timerActive = newState;
		break;
	default:
		qDebug() << "strange signal was sent, num:" << num << "newState:" << newState;
		break;
	}
}

void downloads::timeRemainsUpdate()
{
	if(timeUntilUpdate() < 3)
	{
		setStatus(tr("Preparing to update..."));
		seconds=0;
		timeRemains.stop();
		timerActive = false;
	}
	else
	{
		setStatus(tr("Awaiting update"));
		seconds++;
	}
}

//data manipulation
void downloads::setIndex(int newIndex)
{
	index = newIndex;
}

void downloads::clearInfo()
{
	hashCodes.clear();
}

void downloads::setReply(QNetworkReply *reply)
{
	download->reply = reply;
}

void downloads::setStop(bool newState)
{
	download->stop = newState;
	if(download->stop)
	{
		timer.stop();
		timeRemains.stop();
		timerActive=false;
		seconds=0;
		setStatus(tr("Stopped"));
	}
}

void downloads::setStatus(QString newStatus)
{
	download->setStatus(newStatus);
}

void downloads::nullCounters()
{
	download->imageCount = 0;
	download->imagesDownloaded = 0;
}

void downloads::stopReplies()
{
	for(int i=0;i<download->replies->count();i++)
		download->replies->at(i)->abort();
}

//info
QString downloads::getPath()
{
	return download->path;
}

QString downloads::getUrl()
{
	return download->url;
}

QString downloads::getStatus()
{
	return download->status;
}

int downloads::getPercent()
{
	return download->imageCount == 0 ? 0 : (download->imagesDownloaded*100)/download->imageCount;
}

int downloads::getImagesDownloaded()
{
	return download->imagesDownloaded;
}

int downloads::getImagesFound()
{
	return download->imageCount;
}

bool downloads::isTimerActive()
{
	return timerActive;
}

int downloads::getSimilarImagesCount()
{
	return download->similarImages;
}

QDateTime downloads::getAdditionTime()
{
    return additionTime;
}

int downloads::getImagesCountInFolder()
{
	QDir dir(getPath());
	QStringList files = dir.entryList(QDir::Files);
	files.removeOne(download->dataBaseName);
	return files.count();
}

int downloads::timeUntilUpdate()
{
	return timer.interval()/1000 - seconds;
}

int downloads::getThreadsCount()
{
	return threadsLimit;
}

int downloads::getUpdateInterval()
{
	return upTime;
}

imageTypes downloads::getAlowedTypes()
{
	return types;
}

//signal-senders
void downloads::imagesCountChanged()
{
	emit infoChanged(index);
	emit infoChanged(true,getImagesDownloaded(),getImagesFound());
}

void downloads::statusChanged()
{
	emit infoChanged(index);
	emit infoChanged(getStatus(), timeUntilUpdate());
}

void downloads::folderInfoUpdate()
{
	emit infoChanged(false,getSimilarImagesCount(),getImagesCountInFolder());
}

//other methods
void downloads::saveToRegistry(bool loading)
{
	QSettings settings(QCoreApplication::organizationName(),QCoreApplication::applicationName());
	if (!loading)
	{
		if(settings.value("settings/rememberThreads").toBool())
		{
			settings.setValue("threads/"+QString::number(index)+"/additionTime",additionTime);
			settings.setValue("threads/"+QString::number(index)+"/updateTime",upTime);
			settings.setValue("threads/"+QString::number(index)+"/threadsLimit",threadsLimit);
			settings.setValue("threads/"+QString::number(index)+"/url", QVariant(getUrl()));
			settings.setValue("threads/"+QString::number(index)+"/path",QVariant(getPath()));
			settings.setValue("threads/"+QString::number(index)+"/active",QVariant(true));
			settings.setValue("threads/"+QString::number(index)+"/jpg",QVariant(types.jpg));
			settings.setValue("threads/"+QString::number(index)+"/png",QVariant(types.png));
			settings.setValue("threads/"+QString::number(index)+"/gif",QVariant(types.gif));
			settings.setValue("threads/count",QVariant(index+1));
		}
	}
}

downloads::~downloads()
{
	setStop(true);
	stopReplies();
	delete download;
}
